{-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, FlexibleInstances, OverlappingInstances #-}
module Magicloud.Snmp where

import Control.Exception
import Data.Char
import Network (PortNumber, HostName)
import Network.Protocol.NetSNMP
import Data.List
import Data.Typeable
import Magicloud.Jobs
import qualified Data.Map as M

data Service = Service { protocol :: Protocol
                       , host :: HostName
                       , port :: PortNumber }
instance Show Service where
  show (Service pro hos por) = intercalate ":" [ map toLower $ show pro
                                               , hos
                                               , show por ]

data Protocol = UDP
              | TCP
              deriving (Show, Read)

type OID = [Int]
instance Show OID where
  show o = intercalate "." $ map show o

data SnmpException = SnmpException { message :: String }
                   deriving (Show, Typeable)

instance Exception SnmpException

get :: Service -> SnmpVersion -> Community -> OID -> IO SnmpResult
get ser ver com oid_ = do
  result <- snmpGet ver (show ser) com (show oid_)
  case result of
    Left msg -> throw (SnmpException msg)
    Right result_ -> return result_

walk :: Service -> SnmpVersion -> Community -> OID -> IO [SnmpResult]
walk ser ver com oid_ = do
  result <- snmpWalk ver (show ser) com (show oid_)
  case result of
    Left msg -> throw (SnmpException msg)
    Right result_ -> return result_

pGet :: Service -> SnmpVersion -> Community -> [OID] -> IO (M.Map OID (Either SnmpException SnmpResult))
pGet ser ver com oids =
  (start (M.fromList $ zip oids oids) $ get ser ver com) >>=
    wait

pWalk :: Service -> SnmpVersion -> Community -> [OID] -> IO (M.Map OID (Either SnmpException [SnmpResult]))
pWalk ser ver com oids =
  (start (M.fromList $ zip oids oids) $ walk ser ver com) >>=
    wait
